/**
 * @file xtimer.c
 * @author eric
 * @brief
 * @version 0.1
 * @date 2022-04-16
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <stdio.h>
#include "xtimer.h"

static int head_inited = 0;
static struct list_head head;

int xtimer_start(xtimer_t *timer)
{
    list_node_t *node = NULL;
    int find = -1;

    if (head_inited == 0)
    {
        printf("[%s] %d: \r\n", __func__, __LINE__);
        INIT_LIST_HEAD(&head);
        head_inited = 1;
    }
    /* Find the same??? */
    list_for_each_entry(node, &head, list, xtimer_t)
    {
        if (node == timer) /* restart */
        {
            find = 0;
            node->start = xtimer_get_tick();
        }
    }

    /* add new */
    if (find != 0)
    {
        timer->start = xtimer_get_tick();
        list_add(&timer->list, &head);
    }

    return 0;
}

int xtimer_stop(xtimer_t *timer)
{
    list_node_t *node = NULL;
    list_node_t *n = NULL;
    int find = -1;

    if (head_inited == 0)
    {
        return -404;
    }

    list_for_each_entry_safe(node, n, &head, list, xtimer_t)
    {
        if (node == timer)
        {
            find = 0;
            list_del(&node->list);
        }
    }

    return find;
}

int xtimer_isvalid(xtimer_t *timer)
{
    list_node_t *node = NULL;
    int find = -1;

    if (head_inited == 0)
    {
        return -404;
    }

    list_for_each_entry(node, &head, list, xtimer_t)
    {
        if (node == timer)
        {
            find = 0;
        }
    }

    return find;
}

int xtimer_remain(xtimer_t *timer)
{
    if (timer == 0)
    {
        return -1;
    }

    uint32_t tick = xtimer_get_tick();
    uint32_t remain = timer->timout - (tick - timer->start);

    return remain;
}

void xtimer_loop(void)
{
    list_node_t *node = NULL;
    list_node_t *n = NULL;
    uint32_t tick = 0;

    if (head_inited == 0)
    {
        INIT_LIST_HEAD(&head);
        head_inited = 1;
    }

    /* Find the same??? */
    list_for_each_entry_safe(node, n, &head, list, xtimer_t)
    {
        tick = xtimer_get_tick();
        if ((tick - node->start) > node->timout)
        {
            if (node->opt == XTIMER_SINGLE)
            {
                list_del(&node->list);
            }
            if (node->callback != NULL)
            {
                node->callback(node);
                node->start = tick;
            }
        }
    }
}
